// Copyright 2013 Vedran Vuk. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package irc

import (
	"strings"
)

func isNum(s string) bool {
	return strings.ContainsAny(s, "0123456789")
}

// Strips IRC text formatting codes from "text" and returns the result.
func StripControlCodes(text string) (r string) {
	c := strings.Split(text, "")
	m := 0
	i := 0
	for i < len(c) {
		switch m {
		case 0:
			switch rune(c[i][0]) {
			case 0x02, 0x0F, 0x16, 0x1D, 0x1F:
				i++
				continue
			case 0x03:
				m = 1
			default:
				r += c[i]
			}
		case 1:
			if isNum(c[i]) {
				m = 2
			} else {
				m = 0
				continue
			}
		case 2:
			if isNum(c[i]) {
				m = 3
			} else if c[i] == "," {
				m = 4
			} else {
				m = 0
				continue
			}
		case 3:
			if c[i] == "," {
				if i+1 < len(c) {
					if isNum(c[i+1]) {
						m = 4
					} else {
						m = 0
						continue
					}
				} else {
					m = 0
					continue
				}
				m = 4
			} else {
				m = 0
				continue
			}
		case 4:
			if isNum(c[i]) {
				m = 5
			} else {
				m = 0
				continue
			}
		case 5:
			if isNum(c[i]) {
				m = 0
			} else {
				m = 0
				continue
			}
		}
		i++
	}
	return
}

// Split "msg" to array of string of "max" length which is expressed in bytes.
// Splitting is done at UTF-8 unicode points and resulting strings are ensured
// to be less than or equal to "max" bytes in length.
func SplitMsg(msg string, max int) (out []string) {
	if len(msg) > max {
		u := strings.Split(msg, "")
		l := len(u)
		i := 0
		for i < l {
			s := ""
			for i < l {
				if len(s)+len(u[i]) > max {
					break
				} else {
					s = s + u[i]
					i++
				}
			}
			out = append(out, s)
		}
	} else {
		out = append(out, msg)
	}
	return
}

// Limits "msg" to "max" length which is expressed in bytes.
// Limiting is done at UTF-8 unicode point and resulting string is ensured
// to be less than or equal to "max" bytes in length.
func LimitMsg(msg string, max int) string {
	if len(msg) > max {
		u := strings.Split(msg, "")
		i := 0
		s := ""
		for i < len(u) {
			if len(s)+len(u[i]) > max {
				break
			}
			s = s + u[i]
			i++
		}
		return s
	}
	return msg
}

// Parses out the channel modes from a nickname with channel mode prefix(es)
// For example: s with value "&@somenick" will return "somenick" and a int 
// union of channel modes.
func ParseChannelModes (s string) (nickName string, channelMode int) {
	i := 0
	for i < len(s) {
		switch string(s[i]) {
			case "~": channelMode = channelMode | CmOwner
			case "&": channelMode = channelMode | CmAdmin
			case "@": channelMode = channelMode | CmOp
			case "%": channelMode = channelMode | CmHalfOp
			case "+": channelMode = channelMode | CmVoice
			default: return s[i:], channelMode
		}
		i++
	}
	return "", 0	
}